package edu.cicese.alz.reports;

import edu.cicese.alz.MapData;
import edu.cicese.alz.SwingComponent;
import edu.cicese.alz.TimeUtil;
import edu.cicese.alz.swing.SwingUtil;
import org.openstreetmap.gui.jmapviewer.MapViewer;
import org.openstreetmap.gui.jmapviewer.OsmFileCacheTileLoader;
import org.openstreetmap.gui.jmapviewer.OsmTileLoader;
import org.openstreetmap.gui.jmapviewer.interfaces.TileLoader;
import org.openstreetmap.gui.jmapviewer.interfaces.TileSource;
import org.openstreetmap.gui.jmapviewer.tilesources.BingAerialTileSource;
import org.openstreetmap.gui.jmapviewer.tilesources.OsmTileSource;

import javax.imageio.ImageIO;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.InputMap;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

/**
 * Created by: Eduardo Quintana Contreras
 * Date: 6/07/12
 * Time: 01:17 PM
 */
public class FrameMap extends SwingComponent {

	private MapViewer pMap;
	private MapData mapData;

	private boolean done;

	private JLabel lblDate;

//	private SimpleDateFormat df = new SimpleDateFormat("dd/MM/yyyy");
//	private SimpleDateFormat dfFolder = new SimpleDateFormat("yyyy-MM-dd");


	public FrameMap(MapData mapData, String date) {
		this.mapData = mapData;

		//TODO Send to main
//		System.setProperty("http.proxyHost", "158.97.7.197");
//		System.setProperty("http.proxyPort", "3128");

		setTitle("User: " + mapData.getUserID() + " - " + date);

//		Rectangle window = getBounds();
		Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
//		setLocation((screen.width - window.width) / 2, (screen.height - window.height) / 2);

		setSize(screen.width, screen.height);
		setExtendedState(JFrame.MAXIMIZED_BOTH);

		initComponents();
	}


	private void initComponents() {
		pMap = new MapViewer(mapData);

		pMap.setBorder(BorderFactory.createCompoundBorder(
				BorderFactory.createLineBorder(Color.LIGHT_GRAY, 1),
				BorderFactory.createLineBorder(Color.WHITE, 4)));

		JPanel pContent = new JPanel(new GridBagLayout());
		GridBagConstraints gbc = new GridBagConstraints();

		Box boxSettings = Box.createVerticalBox();
		boxSettings.setMinimumSize(new Dimension(150, 100));
		boxSettings.setOpaque(true);
		boxSettings.setBackground(Color.WHITE);
		boxSettings.setBorder(BorderFactory.createCompoundBorder(
				BorderFactory.createLineBorder(Color.LIGHT_GRAY, 1),
				BorderFactory.createLineBorder(Color.WHITE, 4)));

		// Row 1
		gbc.gridx = 0;
		gbc.gridy = 0;
		gbc.weightx = 0;
		gbc.weighty = 1;
		gbc.fill = GridBagConstraints.BOTH;
		gbc.anchor = GridBagConstraints.FIRST_LINE_START;
		gbc.insets = new Insets(5, 5, 5, 5);
		pContent.add(boxSettings, gbc);

		gbc.gridx = 1;
		gbc.gridy = 0;
		gbc.weightx = 0.5;
		gbc.weighty = 1;
		gbc.insets = new Insets(5, 0, 5, 5);
		pContent.add(pMap, gbc);

		pContent.setBackground(SwingUtil.cBackground);
		setContentPane(pContent);


		// Fit markers
		JButton btnFitMarkers = SwingUtil.createButton("Fit markers", null, null, Color.WHITE, 80, 20);
		btnFitMarkers.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				pMap.setDisplayToFitMapMarkers();
			}
		});

		JButton btnSaveMap = createButton("", "Save map", "b_save", Color.WHITE);
		btnSaveMap.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				saveMap("D:\\.idp\\", System.currentTimeMillis() + ".png");
			}
		});

		// Tile source
		final JComboBox cbTileSourceSelector = SwingUtil.createComboBox(new TileSource[]{new OsmTileSource.Mapnik(), new BingAerialTileSource()}, 200, 20);
		cbTileSourceSelector.addItemListener(new ItemListener() {
			public void itemStateChanged(ItemEvent e) {
				pMap.setTileSource((TileSource) e.getItem());
			}
		});
		cbTileSourceSelector.setSelectedIndex(mapData.getLayerType());
		pMap.setTileSource((TileSource) cbTileSourceSelector.getSelectedItem());

		// Tile loader
		JComboBox cbTileLoaderSelector;
		try {
			cbTileLoaderSelector = SwingUtil.createComboBox(new TileLoader[]{new OsmFileCacheTileLoader(pMap), new OsmTileLoader(pMap)}, 200, 20);
		} catch (IOException e) {
			cbTileLoaderSelector = SwingUtil.createComboBox(new TileLoader[]{new OsmTileLoader(pMap)}, 200, 20);
		}
		cbTileLoaderSelector.addItemListener(new ItemListener() {
			public void itemStateChanged(ItemEvent e) {
				pMap.setTileLoader((TileLoader) e.getItem());
			}
		});
		pMap.setTileLoader((TileLoader) cbTileLoaderSelector.getSelectedItem());

		// Show/hide markers
		final JCheckBox chbShowMarkers = SwingUtil.createCheckBox("Show markers");
		chbShowMarkers.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				mapData.setShowingMarkers(chbShowMarkers.isSelected());
				pMap.repaint();
			}
		});

		// Show/hide tracks
		final JCheckBox chbShowTracks = SwingUtil.createCheckBox("Show tracks");
		chbShowTracks.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				mapData.setShowingTracks(chbShowTracks.isSelected());
				pMap.repaint();
			}
		});

		// Show/hide labels
		final JCheckBox chbShowLabels = SwingUtil.createCheckBox("Show labels");
		chbShowLabels.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				mapData.setShowingLabels(chbShowLabels.isSelected());
				pMap.repaint();
			}
		});


		// Show/hide locations
		final JCheckBox chbShowLocations = SwingUtil.createCheckBox("Show locations");
		chbShowLocations.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				mapData.setShowingLocations(chbShowLocations.isSelected());
				pMap.repaint();
			}
		});

		// Show/hide grid
		final JCheckBox chbShowGrid = SwingUtil.createCheckBox("Show grid");
		chbShowGrid.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				mapData.setShowingGrid(chbShowGrid.isSelected());
				pMap.repaint();
			}
		});

		// Show/hide zoom controls
		final JCheckBox chbShowZoomControls = SwingUtil.createCheckBox("Show zoom controls");
		chbShowZoomControls.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				pMap.setShowingZoomControl(chbShowZoomControls.isSelected());
			}
		});

		// Show/hide marker controls
		final JCheckBox chbShowMarkerControls = SwingUtil.createCheckBox("Show marker controls");
		chbShowMarkerControls.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				pMap.setShowingMarkerControl(chbShowMarkerControls.isSelected());
			}
		});

		if (mapData.getDate() != null) {
			lblDate = new JLabel();
			lblDate.setBounds(5, 550, 100, 30);
			lblDate.setText(TimeUtil.getStringDateFromMs(mapData.getDate().getTime(), TimeUtil.calendarDateFormat));
		}

		chbShowMarkers.setSelected(mapData.isShowingMarkers());
		chbShowLocations.setSelected(mapData.isShowingLocations());
		chbShowTracks.setSelected(mapData.isShowingTracks());
		chbShowLabels.setSelected(mapData.isShowingLabels());
		chbShowGrid.setSelected(mapData.isShowingGrid());
		chbShowZoomControls.setSelected(mapData.isShowingZoomControl());
		chbShowMarkerControls.setSelected(mapData.isShowingMarkerControl());

		pMap.setShowingZoomControl(chbShowZoomControls.isSelected());
		pMap.setShowingMarkerControl(chbShowMarkerControls.isSelected());

		Box boxTop = Box.createHorizontalBox();
		boxTop.add(btnFitMarkers);
		boxTop.add(Box.createHorizontalGlue());
		boxTop.add(btnSaveMap);
		boxTop.setAlignmentX(Component.LEFT_ALIGNMENT);

		boxSettings.add(boxTop);
		boxSettings.add(Box.createVerticalStrut(2));
		boxSettings.add(cbTileSourceSelector);
		boxSettings.add(Box.createVerticalStrut(2));
		boxSettings.add(cbTileLoaderSelector);
		boxSettings.add(Box.createVerticalStrut(2));
		boxSettings.add(chbShowMarkers);
		boxSettings.add(Box.createVerticalStrut(2));
		boxSettings.add(chbShowLocations);
		boxSettings.add(Box.createVerticalStrut(2));
		boxSettings.add(chbShowTracks);
		boxSettings.add(Box.createVerticalStrut(2));
		boxSettings.add(chbShowLabels);
		boxSettings.add(Box.createVerticalStrut(2));
		boxSettings.add(chbShowGrid);
		boxSettings.add(Box.createVerticalStrut(2));
		boxSettings.add(chbShowZoomControls);
		boxSettings.add(Box.createVerticalStrut(2));
		boxSettings.add(chbShowMarkerControls);

		Action actionSave = new AbstractAction() {
			public void actionPerformed(ActionEvent e) {
//				Date d;
//				String dateFolder = "";
//				try {
//					d = df.parse(date);
//					dateFolder = dfFolder.format(d);
//				} catch (ParseException e1) {
//					e1.printStackTrace();
//				}
//				saveMap("D:\\_proyectoAlz\\analysis\\users\\" + userID + System.currentTimeMillis());
			}
		};
		Action actionFit = new AbstractAction() {
			public void actionPerformed(ActionEvent e) {
				pMap.setDisplayToFitMapMarkers();
			}
		};
		Action actionAddPoint = new AbstractAction() {
			public void actionPerformed(ActionEvent e) {
				pMap.addPoint();
			}
		};
		Action actionRemovePoint = new AbstractAction() {
			public void actionPerformed(ActionEvent e) {
				pMap.removePoint();
			}
		};
		Action actionBeginning = new AbstractAction() {
			public void actionPerformed(ActionEvent e) {
				pMap.setPoints(0);
			}
		};
		Action actionEnding = new AbstractAction() {
			public void actionPerformed(ActionEvent e) {
				pMap.setPoints(pMap.jsMarkers.getMaximum());
			}
		};
		Action actionOne = new AbstractAction() {
			public void actionPerformed(ActionEvent e) {
				pMap.setTileSource((TileSource) cbTileSourceSelector.getItemAt(0));
			}
		};
		Action actionTwo = new AbstractAction() {
			public void actionPerformed(ActionEvent e) {
				pMap.setTileSource((TileSource) cbTileSourceSelector.getItemAt(1));
			}
		};
//		Action actionThree = new AbstractAction() {
//			public void actionPerformed(ActionEvent e) {
//				pMap.setTileSource((TileSource) cbTileSourceSelector.getItemAt(2));
//			}
//		};
//		Action actionFour = new AbstractAction() {
//			public void actionPerformed(ActionEvent e) {
//				pMap.setTileSource((TileSource) cbTileSourceSelector.getItemAt(3));
//			}
//		};

		InputMap inputMap = getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
		ActionMap actionMap = getRootPane().getActionMap();

		inputMap.put(KeyStroke.getKeyStroke("control S"), "save");
		inputMap.put(KeyStroke.getKeyStroke("F"), "fit");
		inputMap.put(KeyStroke.getKeyStroke("RIGHT"), "add");
		inputMap.put(KeyStroke.getKeyStroke("LEFT"), "remove");
		inputMap.put(KeyStroke.getKeyStroke("HOME"), "beginning");
		inputMap.put(KeyStroke.getKeyStroke("END"), "ending");
		inputMap.put(KeyStroke.getKeyStroke("NUMPAD1"), "one");
		inputMap.put(KeyStroke.getKeyStroke("NUMPAD2"), "two");
//		inputMap.put(KeyStroke.getKeyStroke("NUMPAD3"), "three");
//		inputMap.put(KeyStroke.getKeyStroke("NUMPAD4"), "four");

		actionMap.put("save", actionSave);
		actionMap.put("fit", actionFit);
		actionMap.put("add", actionAddPoint);
		actionMap.put("remove", actionRemovePoint);
		actionMap.put("beginning", actionBeginning);
		actionMap.put("ending", actionEnding);
		actionMap.put("one", actionOne);
		actionMap.put("two", actionTwo);
//		actionMap.put("three", actionThree);
//		actionMap.put("four", actionFour);


		setVisible(true);
		pMap.setDisplayToFitMapMarkers();
	}

	public MapViewer getMap() {
		return pMap;
	}

	public MapData getMapData() {
		return mapData;
	}

	public void saveMap(String dir, String filename) {
		BufferedImage bi = new BufferedImage(pMap.getSize().width, pMap.getSize().height, BufferedImage.TYPE_INT_ARGB);
		Graphics2D g2 = bi.createGraphics();
		pMap.paint(g2);
		g2.dispose();
		try {
			new File(dir).mkdirs();
			ImageIO.write(bi, "png", new File(dir + filename));
//			if (new File(dir).mkdirs()){
//				ImageIO.write(bi, "png", new File(dir + filename));
//			}
//			else {
//				System.out.println("Couldn't create output directory");
//			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}


	public void done() {
		done = true;
	}

	public boolean isDone() {
		return done;
	}
}
